#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <QDesktopServices>
#include <QUrl>
#include <QFileDialog>
#include <QKeyEvent>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QSettings>
#include <QMessageBox>

#include "mytask.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->lcd_counter->display(ui->spin_hours->value()*60*60+ui->spin_minutes->value()*60+ui->spin_seconds->value());

    connect(ui->btn_new, &QPushButton::clicked, this, &MainWindow::on_new_clicked);
    connect(ui->btn_remove, &QPushButton::clicked, this, &MainWindow::on_remove_clicked);
    connect(ui->btn_help, &QPushButton::clicked, this, &MainWindow::on_help_clicked);

    connect(ui->treeWidget, &QTreeWidget::currentItemChanged, this, &MainWindow::on_selected_item_changed);

    connect (ui->btn_openfile, &QToolButton::clicked, this, [&] {
        ui->line_command->setText(QFileDialog::getOpenFileName(this, tr("Open File - KTimer(clone)")));
    });

    connect(ui->btn_start, &QToolButton::clicked, this, [&]{
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->start();
    });

    connect(ui->btn_pause, &QToolButton::clicked, this, [&]{
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->pause();
    });

    connect(ui->btn_stop, &QToolButton::clicked, this, [&]{
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->stop();
    });

    // TRAYICON
    auto trayIconMenu = new QMenu(this);
    trayIconMenu->addAction(ui->actionrestore);
    trayIconMenu->addSeparator();
    trayIconMenu->addAction(ui->actionquit);

    connect(ui->actionrestore, &QAction::triggered, this, &QWidget::showNormal);
    connect(ui->actionquit, &QAction::triggered, this, [&] {
        if (QMessageBox::question(this, tr("Confirm Quit From System Tray - KTimer(clone)"),
                                     tr("Are you sure you want to quit <b>KTimer(clone)</b>")) == QMessageBox::Yes) {
            save_tasks();
            QCoreApplication::quit();
        }
    });

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/icons/32-apps-ktimer.png"));
    trayIcon->setContextMenu(trayIconMenu);

    connect(trayIcon, &QSystemTrayIcon::activated, this, [&] (auto reason) {
        if (reason == QSystemTrayIcon::DoubleClick)
            QWidget::showNormal();
    });

    trayIcon->show();
    // TRAYICON END

    load_tasks();

    // UPDATE WIDGETS VISUAL
    enable_settings(ui->treeWidget->topLevelItemCount() != 0);
}

void MainWindow::enable_settings(bool enable) {
    ui->frame_settings->setEnabled(enable);
    ui->frame_state->setEnabled(enable);
    ui->btn_remove->setEnabled(enable);
}

void MainWindow::save_tasks() const {
    QSettings settings("RAZORRAZOR", "KTimer(clone)");
    settings.clear();

    settings.setValue("current", ui->treeWidget->currentIndex().row());

    settings.beginWriteArray("Tasks");

    for (int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i) {
        settings.setArrayIndex(i);
        auto const item = static_cast<MyTask*>(ui->treeWidget->topLevelItem(i));
        settings.setValue("hours", item->hours());
        settings.setValue("minutes", item->minutes());
        settings.setValue("seconds", item->seconds());
        settings.setValue("cmd", item->command());
        settings.setValue("loop", item->loop());
        settings.setValue("sooi", item->sooi());
        settings.setValue("ct", item->ct());
        settings.setValue("counter", item->counter());
        settings.setValue("state", item->state());
    }
    settings.endArray();
    settings.sync();
}

void MainWindow::load_tasks() {
    QSettings settings("RAZORRAZOR", "KTimer(clone)");

    int ntask = settings.beginReadArray("Tasks");
    for (int i = 0; i < ntask; ++i) {
        settings.setArrayIndex(i);
        auto task = new MyTask{
            settings.value("hours").toInt(),
            settings.value("minutes").toInt(),
            settings.value("seconds").toInt(),
            settings.value("cmd").toString(),
            settings.value("loop").toBool(),
            settings.value("sooi").toBool(),
            settings.value("ct").toBool()
        };
        task->set_counter(settings.value("counter").toInt());
        task->set_state(settings.value("state").toString());

        add_task(task);
    }
    settings.endArray();

    auto current = settings.value("current").toInt();
    if (current < ui->treeWidget->topLevelItemCount())
        ui->treeWidget->setCurrentItem(ui->treeWidget->topLevelItem(current));
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (!event->spontaneous() || !isVisible())
        return;
    if (trayIcon->isVisible()) {
        hide();
        event->ignore();
    }
}

void MainWindow::keyPressEvent(QKeyEvent *event) {
    if (event->key() == Qt::Key_Escape) {
        hide();
    }
    QMainWindow::keyPressEvent(event);
}

void MainWindow::add_task(MyTask *ptask) {
    connect(ptask, &MyTask::counter_changed, [&] (int counter, QTreeWidgetItem *item) {
        if (ui->treeWidget->currentItem() == item) {
            ui->lcd_counter->display(counter);
            ui->slider_counter->setValue((int)(counter*1.f/((MyTask*)item)->delay()*99));
        }
    });

    connect(ptask, &MyTask::finished, [&] (QTreeWidgetItem *item) {
        auto current = static_cast<MyTask*>(ui->treeWidget->itemBelow(item));
        if (current && current->ct())
            current->start();
    });

    ui->treeWidget->insertTopLevelItem(ui->treeWidget->topLevelItemCount(), ptask);
}

void MainWindow::on_new_clicked() {
    add_task(new MyTask {});
    enable_settings(ui->treeWidget->topLevelItemCount() != 0);
}

void MainWindow::on_remove_clicked() {
    delete ui->treeWidget->currentItem();
    enable_settings(ui->treeWidget->topLevelItemCount() != 0);
}

void MainWindow::on_help_clicked() {
    QDesktopServices::openUrl(QUrl("https://docs.kde.org/stable5/en/ktimer/ktimer/index.html"));
}

void MainWindow::on_selected_item_changed() {
    qDebug() << "changed..." << ui->treeWidget->currentIndex().row();

    if (ui->treeWidget->currentIndex().row() < 0)
        return ;

    // DISCONNECT BEFORE SYNC STATES
    disconnect(ui->line_command, &QLineEdit::textChanged, 0, 0);
    disconnect(ui->spin_hours, &QSpinBox::valueChanged, 0, 0);
    disconnect(ui->spin_minutes, &QSpinBox::valueChanged, 0, 0);
    disconnect(ui->spin_seconds, &QSpinBox::valueChanged, 0, 0);
    disconnect(ui->check_loop, &QCheckBox::checkStateChanged, 0, 0);
    disconnect(ui->check_start_only_one_instance, &QCheckBox::checkStateChanged, 0, 0);
    disconnect(ui->check_consecutive_task, &QCheckBox::checkStateChanged, 0, 0);
    disconnect(ui->slider_counter, &QSlider::sliderMoved, 0, 0);
    disconnect(ui->slider_counter, &QSlider::sliderPressed, 0, 0);

    // SYNC STATES
    auto const current_item = (MyTask*)ui->treeWidget->currentItem();
    ui->line_command->setText(current_item->command());
    ui->spin_hours->setValue(current_item->hours());
    ui->spin_minutes->setValue(current_item->minutes());
    ui->spin_seconds->setValue(current_item->seconds());
    ui->check_loop->setChecked(current_item->loop());
    ui->check_start_only_one_instance->setChecked(current_item->sooi());
    ui->check_consecutive_task->setChecked(current_item->ct());

    ui->lcd_counter->display(current_item->counter());
    ui->slider_counter->setValue((int)(current_item->counter()*1.f/current_item->delay()*99));

    // RECONNECTED
    connect(ui->check_loop, &QCheckBox::checkStateChanged, this, [&](bool checked){
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->set_loop(checked);
    });

    connect(ui->check_start_only_one_instance, &QCheckBox::checkStateChanged, this, [&](bool checked){
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->set_sooi(checked);
    });

    connect(ui->check_consecutive_task, &QCheckBox::checkStateChanged, this, [&](bool checked){
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->set_ct(checked);
    });

    connect(ui->spin_hours, &QSpinBox::valueChanged, this, [&](int value){
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->set_hours(value);
    });

    connect(ui->spin_minutes, &QSpinBox::valueChanged, this, [&](int value){
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->set_minutes(value);
    });

    connect(ui->spin_seconds, &QSpinBox::valueChanged, this, [&](int value){
        qDebug() << "write seconds to item";
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->set_seconds(value);
    });

    connect(ui->line_command, &QLineEdit::textChanged, this, [&] {
        auto item = (MyTask*)ui->treeWidget->currentItem();
        if (item) item->set_command(ui->line_command->text());
    });

    connect(ui->slider_counter, &QSlider::sliderMoved, this, [&](int pos){
        if (auto item = (MyTask*)ui->treeWidget->currentItem()) {
            item->set_counter((int)(item->delay()*pos/99.f));
            ui->lcd_counter->display(item->counter());
        }
    });

    connect(ui->slider_counter, &QSlider::sliderPressed, this, [&] {
        if (auto item = (MyTask*)ui->treeWidget->currentItem()) {
            int pos = ui->slider_counter->value();
            item->set_counter((int)(item->delay()*pos/99.f));
            ui->lcd_counter->display(item->counter());
        }
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}
